﻿#include "ssClockWheel.h"


namespace StarSeeker
{

ssClockWheel::ssClockWheel()
{
	m_tick.tick = 0;
	m_timer.Init(SS_DIFF_TIMER_TYPE_SEC);
	m_pDispatch = 0;
	m_ids.Init(1, 4000000000);
}

ssClockWheel::~ssClockWheel()
{
	ExitThread();
}

void ssClockWheel::BindDispatch(ssTimerDispatch* dis)
{
	m_pDispatch = dis;
}

u32 ssClockWheel::AddTime(u32 interval, ulint param1, ulint param2)
{
	Tick_u tmp = m_tick;
	tmp._l1 += interval % 256;
	tmp._l2 += interval / 256;
	tmp._l3 += interval / 256*256;
	tmp._l4 += interval / 256*256*256;
	ssTimer_s msg;
	msg.time = ssTime::GetTimeNow().u32p;
	msg.interval = tmp.tick;
	msg.param[0] = param1;
	msg.param[1] = param2;
	SS_MUTEX_LOCK(m_mutex)
		msg.subID = m_ids.GetID();
		m_solt[tmp._l1].m_msgList.PushBack(msg);
	SS_MUTEX_UNLOCK(m_mutex)
	return msg.subID;
}

void ssClockWheel::RemoveTimer(u32 timerId)
{
	SS_MUTEX_LOCK(m_mutexDel);
	m_del.insert(timerId);
	SS_MUTEX_UNLOCK(m_mutexDel);
}

void ssClockWheel::ExitThread()
{
	RequestStop();
	ssThreadBase::Sleep(500);
	WaitForExit();
}

void ssClockWheel::AddTick()
{
	Tick_u tmp;
	++m_tick.tick;
	SS_MUTEX_LOCK(m_mutex); //锁定互斥量
	if (m_solt[m_tick._l1].m_msgList.Size() > 0)
	{
		ssList<ssTimer_s>::Iterator itr = m_solt[m_tick._l1].m_msgList.Begin();
		while (itr.IsVaild())
		{
			SS_MUTEX_LOCK(m_mutexDel);
			std::set<u32>::iterator del = m_del.find(itr.Data()->subID);
			if (del != m_del.end())
			{
				itr.Data()->msgID = SS_TIMER_DEL;
				m_del.erase(del);
			}
			SS_MUTEX_UNLOCK(m_mutexDel);

			if (itr.Data()->msgID == SS_TIMER_DEL)
			{
				itr = m_solt[m_tick._l1].m_msgList.EraseItr(itr);
				continue;
			}
			tmp.tick = itr.Data()->interval;
			if (tmp._l2== m_tick._l2 && tmp._l3 == m_tick._l3 && tmp._l4 == m_tick._l4)
			{
				if (m_pDispatch)
					m_pDispatch->Dispatch(SS_TIMER_ONCE, itr.Data()->subID, itr.Data()->param[0], itr.Data()->param[1]);
				itr = m_solt[m_tick._l1].m_msgList.EraseItr(itr);
			}
			else
			{
				++itr;
			}
		}
	}
	SS_MUTEX_UNLOCK(m_mutex);
}

void ssClockWheel::ThreadMemberFunc()
{
	while (!IsRequestStop())
	{
		m_timer.UpdateTime();
		if (m_timer.GetDifference().i32p > 0)
		{
			for (i32 i = 0; i < m_timer.GetDifference().i32p; ++i)
			{
				AddTick();
			}
		}
		ssThreadBase::Sleep(1);
	}
}

}
